#pragma once
#include <time.h>
#include <string>
#include <unistd.h>
#include <iostream>
#include <stdarg.h>
#include <sys/types.h>
#include "LockGuard.hpp"
#include <fstream>
using std::cout;
using std::endl;
using std::string;

pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;

bool gIsSave = false;
const std::string logfile = "log.txt";

#define EnableFile() gIsSave = true
#define EnableScreen() gIsSave = false

enum Level // 设置警告等级
{
    DEBUG = 0,
    INFO,
    WARNING,
    ERROR,
    FATAL
};
string LevelToString(int level) // 将警告等级转成字符串，方便打印输出
{
    switch (level)
    {
    case 0:
        return "Debug";
    case 1:
        return "Info";
    case 2:
        return "Warning";
    case 3:
        return "Error";
    case 4:
        return "Fatal";
    default:
        return "Unknown";
    }
}
string GetTimeString() // 获取一个时间字符串
{
    time_t curtime = time(nullptr); // 获得一个时间戳

    struct tm *nowtime = localtime(&curtime); // 用时间戳形成年月日的日期
    if (nowtime == nullptr)
        return "Node";

    char time_buffer[1024];
    snprintf(time_buffer, 1024, "%d-%d-%d %d:%d:%d",
             nowtime->tm_year + 1900, nowtime->tm_mon + 1, nowtime->tm_mday,
             nowtime->tm_hour, nowtime->tm_min, nowtime->tm_sec);

    return time_buffer;
}

#define LOG(level, format, ...)                                       \
    do                                                                \
    {                                                                 \
        LogMessage(__FILE__, __LINE__, level, format, ##__VA_ARGS__); \
    } while (0);

void SaveFile(const string &filename, const string &message); // 声明一下该函数

void LogMessage(const string &filename, int line, int level, const char *format, ...)
{
    string levelstr = LevelToString(level);
    string timestr = GetTimeString();
    pid_t selfpid = getpid();

    char buffer[1024];
    va_list arg;
    va_start(arg, format); // 对 arg 进行设置
    vsnprintf(buffer, sizeof(buffer), format, arg);
    va_end(arg);

    std::string message = "[" + levelstr + "]" + "[" + timestr + "]" + "[" + filename + "]" + "[" + std::to_string(line) + "]" + "[pid:" + std::to_string(selfpid) + "]" + buffer + "\n";

    LockGuard lockguard(&lock);
    if (gIsSave == 0)
        cout << message;
    else
        SaveFile(logfile, message);
}
void SaveFile(const string &filename, const string &message)
{
    std::ofstream out(filename, std::ios::app);
    // 使用这个构造函数，会自动调用 out.open() 函数，所以不用手动调用了

    if (!out.is_open())
    {
        return;
    }
    out << message;
    out.close();
}
